bitkeeper revision 1.1159.187.17 (41a63c69lFw9w4Qh2aZDluR-6MdrkQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 25 Nov 2004 20:11:21 +0000 (20:11 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 25 Nov 2004 20:11:21 +0000 (20:11 +0000)
More hypercall preemption fixes. do_mmu_update() now correctly remembers the
foreigndom across preempt/resume.

xen/arch/x86/domain.c
xen/arch/x86/memory.c
xen/arch/x86/traps.c
xen/common/dom_mem_ops.c
xen/common/multicall.c
xen/include/xen/sched.h

index f5627a1ebdf28eadba4d42dba6ff6378b8bfecaa..47187ac118c7962db2fb0591c72696f18ad3d66d 100644 (file)
@@ -427,7 +427,8 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
     return 0;
 }
 
-void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...)
+unsigned long hypercall_create_continuation(
+    unsigned int op, unsigned int nr_args, ...)
 {
     struct mc_state *mcs = &mc_state[smp_processor_id()];
     execution_context_t *ec;
@@ -455,6 +456,8 @@ void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...)
     }
 
     va_end(args);
+
+    return op;
 }
 
 #endif
index 4e83af76c2fa8982a9ec59e337b143b9230c93a4..5734f45ba95c2ebbd21420bdc60a9ead85e7a205 100644 (file)
@@ -126,10 +126,9 @@ static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t);
 static struct {
 #define DOP_FLUSH_TLB   (1<<0) /* Flush the TLB.                 */
 #define DOP_RELOAD_LDT  (1<<1) /* Reload the LDT shadow mapping. */
-    unsigned long       deferred_ops;
-    unsigned long       cr0;
+    unsigned long  deferred_ops;
     /* If non-NULL, specifies a foreign subject domain for some operations. */
-    struct domain      *foreign;
+    struct domain *foreign;
 } __cacheline_aligned percpu_info[NR_CPUS];
 
 /*
@@ -1283,18 +1282,22 @@ int do_mmu_update(
 /*
  * We steal the m.s.b. of the @count parameter to indicate whether this
  * invocation of do_mmu_update() is resuming a previously preempted call.
+ * We steal the next 15 bits to remember the current FOREIGNDOM.
  */
-#define MMU_UPDATE_PREEMPTED  (~(~0U>>1))
+#define MMU_UPDATE_PREEMPTED          (~(~0U>>1))
+#define MMU_UPDATE_PREEMPT_FDOM_SHIFT ((sizeof(int)*8)-16)
+#define MMU_UPDATE_PREEMPT_FDOM_MASK  (0x7FFFU<<MMU_UPDATE_PREEMPT_FDOM_SHIFT)
 
     mmu_update_t req;
     unsigned long va = 0, deferred_ops, pfn, prev_pfn = 0;
     struct pfn_info *page;
-    int rc = 0, okay = 1, i, cpu = smp_processor_id();
+    int rc = 0, okay = 1, i = 0, cpu = smp_processor_id();
     unsigned int cmd, done = 0;
     unsigned long prev_spfn = 0;
     l1_pgentry_t *prev_spl1e = 0;
     struct domain *d = current;
     u32 type_info;
+    domid_t domid;
 
     perfc_incrc(calls_to_mmu_update); 
     perfc_addc(num_page_updates, count);
@@ -1304,25 +1307,45 @@ int do_mmu_update(
     /*
      * If we are resuming after preemption, read how much work we have already
      * done. This allows us to set the @done output parameter correctly.
+     * We also reset FOREIGNDOM here.
      */
-    if ( unlikely(count & MMU_UPDATE_PREEMPTED) )
+    if ( unlikely(count&(MMU_UPDATE_PREEMPTED|MMU_UPDATE_PREEMPT_FDOM_MASK)) )
     {
+        if ( !(count & MMU_UPDATE_PREEMPTED) )
+        {
+            /* Count overflow into private FOREIGNDOM field. */
+            MEM_LOG("do_mmu_update count is too large");
+            rc = -EINVAL;
+            goto out;
+        }
         count &= ~MMU_UPDATE_PREEMPTED;
+        domid = count >> MMU_UPDATE_PREEMPT_FDOM_SHIFT;
+        count &= ~MMU_UPDATE_PREEMPT_FDOM_MASK;
         if ( unlikely(pdone != NULL) )
             (void)get_user(done, pdone);
+        if ( (domid != current->id) &&
+             !do_extended_command(0, MMUEXT_SET_FOREIGNDOM | (domid << 16)) )
+        {
+            rc = -EINVAL;
+            goto out;
+        }
     }
 
     if ( unlikely(!array_access_ok(VERIFY_READ, ureqs, count, sizeof(req))) )
-        return -EFAULT;
+    {
+        rc = -EFAULT;
+        goto out;
+    }
 
     for ( i = 0; i < count; i++ )
     {
         if ( hypercall_preempt_check() )
         {
-            hypercall_create_continuation(
+            rc = hypercall_create_continuation(
                 __HYPERVISOR_mmu_update, 3, ureqs, 
-                (count - i) | MMU_UPDATE_PREEMPTED, pdone);
-            rc = __HYPERVISOR_mmu_update;
+                (count - i) |
+                (FOREIGNDOM->id << MMU_UPDATE_PREEMPT_FDOM_SHIFT) | 
+                MMU_UPDATE_PREEMPTED, pdone);
             break;
         }
 
@@ -1459,6 +1482,7 @@ int do_mmu_update(
         ureqs++;
     }
 
+ out:
     if ( prev_pfn != 0 )
         unmap_domain_mem((void *)va);
 
index 5662a6388eea66e22f991439e3216806fe131f87..f07740220b4c95be1ae5a7ceafc87e4f8c2915a6 100644 (file)
@@ -805,11 +805,8 @@ long do_set_trap_table(trap_info_t *traps)
     for ( ; ; )
     {
         if ( hypercall_preempt_check() )
-        {
-            hypercall_create_continuation(
+            return hypercall_create_continuation(
                 __HYPERVISOR_set_trap_table, 1, traps);
-            return __HYPERVISOR_set_trap_table;
-        }
 
         if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT;
 
index 373aee66c0e51b64985290fb7a03736bf74b254b..d675603cdf1299fe7438bb6276d0cc4cb02ffd7e 100644 (file)
 #define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
 
 #define PREEMPT_CHECK(_op)                          \
-    if ( hypercall_preempt_check() ) {              \
-        hypercall_create_continuation(              \
+    if ( hypercall_preempt_check() )                \
+        return hypercall_create_continuation(       \
             __HYPERVISOR_dom_mem_op, 5,             \
             (_op) | (i << START_EXTENT_SHIFT),      \
             extent_list, nr_extents, extent_order,  \
-            (d == current) ? DOMID_SELF : d->id);   \
-        return __HYPERVISOR_dom_mem_op;             \
-    }
+            (d == current) ? DOMID_SELF : d->id)
 
 static long
 alloc_dom_mem(struct domain *d, 
index 04b5a7bdd29aaa5f27d3562c8472a8616cf34669..dfe5e8d69165ed1724289dd2425c162549a9e2ed 100644 (file)
@@ -60,9 +60,8 @@ long do_multicall(multicall_entry_t *call_list, unsigned int nr_calls)
             if ( i < nr_calls )
             {
                 mcs->flags = 0;
-                hypercall_create_continuation(
+                return hypercall_create_continuation(
                     __HYPERVISOR_multicall, 2, &call_list[i], nr_calls-i);
-                return __HYPERVISOR_multicall;
             }
         }
     }
index b0c8d703977d6b5c7918cff881d9350a87d88b9d..c8781f0440b3e974be19b73996d92dcbe606f448 100644 (file)
@@ -218,7 +218,8 @@ void continue_cpu_idle_loop(void);
 
 void continue_nonidle_task(void);
 
-void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...);
+unsigned long hypercall_create_continuation(
+    unsigned int op, unsigned int nr_args, ...);
 #define hypercall_preempt_check() \
     (unlikely(softirq_pending(smp_processor_id())))